# -*- coding: utf-8 -*-
import logging
import urllib
from datetime import date, datetime, timedelta
from webapp2_extras import json
from webapp2_extras.i18n import gettext as _
from webapp2_extras.auth import InvalidAuthIdError, InvalidPasswordError
from lib.handlers import BaseApiHandler
from lib import utils
from application import models
from google.appengine.ext import ndb, blobstore
from google.appengine.ext.webapp import blobstore_handlers
from google.appengine.datastore.datastore_query import Cursor
from google.appengine.api.images import get_serving_url, delete_serving_url
from google.appengine.api import users, memcache


class PingHandler(BaseApiHandler):
    """
    Ping Handler Class.

    Handle ping request from Web Application code.
    """

    def get(self):
        """
        GET Request called on every 5 seconds to query memcache if there is any change.
        """
        out = {}
        i = self.request.get('i')
        q = self.request.get('q')
        # s = self.request.get('s')
        if not q or not i:
            self.abort(501)
        m_key = "cc:%s_%s" % q, i
        res = memcache.get(m_key)
        if len(res) > 0:
            out['q'] = json.decode(res)
        self.out(out)

    def post(self):
        out = {}
        # i = self.request.get('i')
        q = self.request.get('q')
        # s = self.request.get('s')
        if not q:
            self.abort(501)
        if q == "icount" or q == "ucount":
            if not self.admin:
                self.response.out.write(json.encode(dict(status="error", message="Unauthorized")))
                return
            m_key = "app:ajani:%s" % q
        else:
            user_info = self.get_user_info(mem=True)
            if not user_info:
                self.response.out.write(json.encode(dict(status="error", message="Unauthorized")))
                return
            m_key = "app:ajani:%s%s" % (q, user_info['id'])
        res = memcache.get(m_key)
        logging.info(m_key)
        logging.info(res)
        # if len(res) > 0:
        #     out['q'] = json.decode(res)
        if res:
            out['status'] = "success"
            out['message'] = "success"
            if q == "ibr":
                out['data'] = len(json.decode(res)) == 0
            else:
                out['data'] = json.decode(res) if isinstance(res, str) else res

        self.out(out)

    def put(self):
        q = self.request.get('q')
        u = self.request.get('u')
        if not q:
            self.abort(501)
        if not u:
            id = utils.random_string(12)
        else:
            id = self.user_id()
        m_key = "cc:%s_%s" % q, id
        while True:
            val = memcache.get(m_key)
            if val:
                id = utils.random_string(12)
                m_key = "cc:%s_%s" % q, id
            else:
                break
        memcache.add(m_key, '')
        self.out(dict(id=id))


class UserCheckApiHandler(BaseApiHandler):
    """docstring for UserApiHandler"""

    def get(self):
        """
        Ping handler that get called on every changed path.

        Accept param 'q' for detailed user info.
        Accept param 'u' for redirect url after login.

        Will return 401 HTTP Code if not requested for 'q',
        or else a json object containing info for user login requirement.

        If no user info stored in datastore yet, will return a json object
        containing info for further POST request that have to be made by client
        to create initial user info.
        """
        detail = self.request.get('q')
        user = self.user
        if not user:
            if not detail:
                self.response.out.write(json.encode(dict(status="error", message="Unauthorized")))
                return
            elif detail == "detail":
                out = dict(
                    status="error",
                    message="Login Required",
                    url=users.create_login_url(self.request.get('u') + "&f=1")
                )
                self.out(out)
            else:
                self.out([])
        else:
            # logging.info(self.get_user_info)
            user_info = self.get_user_info(mem=True)
            if user_info:
                admin = self.admin

                # img = get_serving_url(user_info.img, size=100) if user_info.img else None
                # if img:
                #     img = "<img src='%s'/>" % img
                # display_name = user_info.display if user_info.display else user.nickname()
                if not detail:
                    out = dict(
                        status="success",
                        message="success",
                        display=user_info.get('display'),
                        img=user_info.get('img'),
                        admin=admin != None
                    )
                elif detail == "detail":
                    out = dict(
                        status="success",
                        message="success",
                        user=user_info,
                        admin=admin != None
                    )
                else:
                    out = []
            else:
                email = user.email()
                out = dict(
                    status="success",
                    message="uninitialized",
                    display=email.split("@")[0]
                )
            self.out(out)

    def post(self):
        """
        Initialize user info into datastore.
        """
        user = self.user
        if user:
            email = user.email()
            user_info = models.User(
                id=user.user_id(), email=user.email(), display=email.split("@")[0]
            )
            key = user_info.put()
            out = dict(
                status="success",
                message="success",
                user=dict(
                    admin=False,
                    id=key.id(),
                    display=user_info.display,
                    email=user_info.email
                )
            )
            mem = dict(
                id=key.id(),
                display=user_info.display,
                name=user_info.name,
                email=user_info.email,
                country=user_info.country,
                gender=user_info.gender,
                bio=user_info.bio,
                address=user_info.address,
                phone=user_info.phone,
                dob_y=None,
                dob_m=None,
                dob_d=None,
                dob=None,
                img=None
            )
            memcache.add("app:ajani:ui%s" % key.id(), utils.model_encode(mem))
            self.out(out)
        else:
            self.out(dict(status="error", message="error"))

    def put(self):
        """
        Update user info in datastore
        """
        out = dict()
        form = json.decode(self.request.body)
        form = form['user']
        user = self.user
        if user:
            try:
                user_info = self.get_user_info()

                try:
                    img = get_serving_url(user_info.img, size=100) if user_info.img else None
                    if img:
                        img = "<img src='%s'/>" % img
                    user_info.display = form['display']
                    user_info.name = form['name']
                    user_info.dob = date(form['dob_y'], form['dob_m'] + 1, form['dob_d'])
                    user_info.country = form['country']
                    user_info.gender = form['gender']
                    user_info.bio = form['bio']
                    user_info.address = form['address']
                    user_info.phone = form['phone']
                    # user_info.img = form['img']
                    user_info.put()

                    out['status'] = "success"
                    out['message'] = _('Thanks, your settings have been saved.')
                    out['user'] = dict(
                        id=user_info.key.id(),
                        display=user_info.display,
                        name=user_info.name,
                        email=user_info.email,
                        country=user_info.country,
                        gender=user_info.gender,
                        bio=user_info.bio,
                        address=user_info.address,
                        phone=user_info.phone,
                        dob_y=user_info.dob.year,
                        dob_m=user_info.dob.month - 1,
                        dob_d=user_info.dob.day,
                        dob=user_info.dob.strftime("%d %B %Y"),
                        img=img
                    )
                    memcache.replace("app:ajani:ui" % user_info.key.id(), )
                    self.out(out)

                except (AttributeError, KeyError, ValueError), e:
                    logging.error(e)
                    out['status'] = "error"
                    out['message'] = _('Unable to update profile. Please try again later.')
                    self.out(out)

            except (AttributeError, TypeError), e:
                logging.error(e)
                out['status'] = "error"
                out['message'] = _('Sorry you are not logged in.')
                self.out(out)
        else:
            self.out(dict(status="error", message="error"))


class UserRegisterHandler(BaseApiHandler):
    """docstring for UserRegisterHandler"""

    def get(self):
        self.abort(403)

    def post(self):
        out = dict(status="", message="")

        form = json.decode(self.request.body)
        username = form['username'].lower()
        password = form['password'].strip()
        email = form['email'].lower()
        name = form['firstname'].strip()
        last_name = form['lastname'].strip()

        # Password to SHA512
        password = utils.hashing(password, self.app.config.get('salt'))

        # Passing password_raw=password so password will be hashed
        # Returns a tuple, where first value is BOOL.
        # If True ok, If False no new user is created
        unique_properties = ['username', 'email']
        auth_id = "own:%s" % username
        user = self.auth.store.user_model.create_user(
            auth_id, unique_properties, password_raw=password,
            username=username, name=name, last_name=last_name, email=email,
            ip=self.request.remote_addr
        )

        if not user[0]:
            out['status'] = "error"
            if "username" in str(user[1]):
                out['message'] = _('Sorry, The username %s is already registered.' % '<strong>{0:>s}</strong>'.format(username))
            elif "email" in str(user[1]):
                out['message'] = _('Sorry, The email %s is already registered.' % '<strong>{0:>s}</strong>'.format(email))
            else:
                out['message'] = _('Sorry, The user is already registered.')
        else:
            # User registered successfully
            out['status'] = "success"
            out['message'] = _('You were successfully registered. Please check your email to activate your account.')

        # self.response.headers['Content-Type'] = "text/plain"
        self.response.out.write(json.encode(out))


class UserSigninHandler(BaseApiHandler):
    """docstring for UserSigninHandler"""

    def get(self):
        self.abort(403)

    def post(self):
        out = dict(status="", message="")
        form = json.decode(self.request.body)

        username = form['username_email'].lower()

        try:
            if utils.is_email_valid(username):
                user = models.User.get_by_email(username)
                if user:
                    auth_id = user.auth_ids[0]
                else:
                    raise InvalidAuthIdError
            else:
                auth_id = "own:%s" % username
                user = models.User.get_by_auth_id(auth_id)

            password = form['password'].strip()
            remember_me = form['remember_me']

            # Password to SHA512
            password = utils.hashing(password, self.app.config.get('salt'))

            # Try to login user with password
            # Raises InvalidAuthIdError if user is not found
            # Raises InvalidPasswordError if provided password
            # doesn't match with specified user
            self.auth.get_user_by_password(auth_id, password, remember=remember_me)

            out['status'] = "success"
            out['message'] = "Welcome back"

            admin_key = ndb.Key(models.User, user.key.id(), models.Admin, "adm:%s" % user.username)
            admin = models.Admin.query(ancestor=admin_key)
            out['user'] = dict(username=user.username, admin=admin != None)

            self.out(out)

        except (InvalidAuthIdError, InvalidPasswordError):
            # Returns error message to self.response.write in
            # the BaseHandler.dispatcher
            out['status'] = "error"
            out['message'] = _("Your username or password is incorrect. Please try again (make sure your caps lock is off)")
            self.out(out)


class UserSignoutHandler(BaseApiHandler):
    """docstring for UserSignoutHandler"""

    def get(self):
        out = dict()
        out['message'] = 'error'
        out['status'] = 'error'
        out['url'] = '/'
        if self.user:
            out['message'] = 'success'
            out['status'] = 'success'
            out['url'] = users.create_logout_url(self.request.get('u'))
        self.out(out)

    # def post(self):
    #     out = dict(status="", message="")
    #     if self.user:
    #         out['message'] = _("You've signed out successfully. Warning: Please clear all cookies and logout "
    #                     "of OpenId providers too if you logged in on a public computer.")
    #         out['status'] = "success"

    #     self.auth.unset_session()
    #     self.response.out.write(json.encode(out))


#######################################################
### Items' Resource
###
###
#######################################################


class ItemQueryAllHandler(BaseApiHandler):
    """docstring for ItemQueryAllHandler"""

    def get(self):
        q = self.request.get('q', default_value='')
        if q == 'home':
            newest = dict(items=models.Item.get_latest(), users=[], imgs=[])
            pops = dict(items=models.Item.get_popular(), users=[], imgs=[])
            for item in newest['items']:
                user_key = item.key.parent()
                user = user_key.get()
                newest['users'].append(dict(display=user.display, id=user_key.id()))

                if item.img:
                    newest['imgs'].append(dict(prev=get_serving_url(item.img[0], 200), orig=get_serving_url(item.img[0]), th=get_serving_url(item.img[0], 100)))

            for item in pops['items']:
                user_key = item.key.parent()
                user = user_key.get()
                pops['users'].append(dict(display=user.display, id=user_key.id()))

                if item.img:
                    pops['imgs'].append(dict(prev=get_serving_url(item.img[0], 200), orig=get_serving_url(item.img[0]), th=get_serving_url(item.img[0], 100)))

            self.out(dict(newest=newest, pops=pops))
        else:
            u = self.request.get('u', default_value=None)
            p = self.request.get('p', default_value=None)
            c = self.request.get('c', default_value=None)
            cat = self.request.get('cat', default_value=None)
            forw = True if p != 'prev' else False
            curs = Cursor(urlsafe=c)
            out = dict(next_url="", prev_url="", items=None, users=[], imgs=[])

            if u:
                user_info = self.get_user_info(mem=True)
                if user_info:
                    query = models.Item.query(ancestor=ndb.Key(models.User, user_info['id']))
                else:
                    self.response.out.write(json.encode(dict(status="error", message="Unauthorized")))
                    return
            else:
                if cat:
                    query = models.Item.query(ndb.AND(models.Item.categories == cat))
                else:
                    query = models.Item.query()
            PAGE_SIZE = 10

            if forw:
                items, next_cursor, more = query.order(-models.Item.created).fetch_page(PAGE_SIZE, start_cursor=curs)
                if next_cursor and more:
                    out['next_url'] = self.uri_for('items-list', p="next", c=next_cursor.urlsafe())
                if c:
                    out['prev_url'] = self.uri_for('items-list', p="prev", c=curs.reversed().urlsafe())
            else:
                items, next_cursor, more = query.order(models.Item.created).fetch_page(PAGE_SIZE, start_cursor=curs)
                items = list(reversed(items))
                if next_cursor and more:
                    out['prev_url'] = self.uri_for('items-list', p="prev", c=next_cursor.urlsafe())
                out['next_url'] = self.uri_for('items-list', p="next", c=curs.reversed().urlsafe())

            if not u:
                for item in items:
                    user_key = item.key.parent()
                    user = user_key.get()
                    out['users'].append(dict(display=user.display, id=user_key.id()))

                    if item.img:
                        out['imgs'].append(dict(prev=get_serving_url(item.img[0], 200), orig=get_serving_url(item.img[0]), th=get_serving_url(item.img[0], 100)))

            out['items'] = items

            self.out(out)


class ItemQueryLatest(BaseApiHandler):
    """docstring for ItemQueryLatest"""

    def get(self):
        out = models.Item.get_latest()
        self.out(out)


class ItemQueryPopular(BaseApiHandler):
    """docstring for ItemQueryPopular"""

    def get(self):
        out = models.Item.get_popular()
        self.out(out)


class ItemPostNew(BaseApiHandler):
    """docstring for ItemPostNew"""

    def post(self):
        #: TODO: no error handler
        out = dict(status="error", message="Error")
        user = self.get_user_info(mem=True)
        if user:
            form = json.decode(self.request.body)
            exp_y = getattr(form, 'exp_y', None)
            exp_m = getattr(form, 'exp_m', None)
            exp_d = getattr(form, 'exp_d', None)
            if not exp_y and not exp_m and not exp_d:
                exp = datetime.now() + timedelta(30)
            else:
                exp = datetime(int(exp_y), int(exp_m) + 1, int(exp_d))
            item = models.Item(
                parent=ndb.Key(models.User, user['id']),
                expire=exp,
                active=form['act'] == 'true',
                title=form['title'],
                desc=dict(raw=form['desc'], strp=utils.remove_tags(form['desc'])),
                price=form['price'],
                img=[blobstore.BlobInfo.get(img['key']).key() for img in form['imgs']],
                private=form['private'] == "true",
                categories=[form['category']]
            )
            item_key = item.put()
            if item_key:
                out['status'] = "success"
                out['message'] = "Item Successfully Posted."
        self.out(out)


class ItemSearchHandler(BaseApiHandler):
    """docstring for ItemSearchHandler"""

    def get(self):
        q = self.request.get('q', default_value=None)
        if q:
            result = self.search_item(q)
            if result:
                out = []
                for res in result.results:
                    obj = {}
                    for field in res.fields:
                        obj[field.name] = field.value
                    obj['key'] = res.doc_id
                    out.append(obj)
                self.out(out)
            else:
                self.out([])
        else:
            self.out([])


#######################################################
### Upload Handlers
###
###
#######################################################
class UploadURLHandler(BaseApiHandler):
    """docstring for UploadURLHandler"""

    def get(self):
        q = self.request.get('q')
        if q:
            upload_url = blobstore.create_upload_url("/_/upload-i%s" % q)
        else:
            upload_url = blobstore.create_upload_url("/_/upload-iprofile")
        self.response.headers['Content-Type'] = 'application/json'
        self.response.out.write('"' + upload_url + '"')


class UploadImageProfileHandler(blobstore_handlers.BlobstoreUploadHandler):
    """docstring for UploadImageProfileHandler"""

    def post(self):
        upload_files = self.get_uploads('userimage')
        blob_info = upload_files[0]
        self.redirect('/_/upload-iprofile-callback/%s' % blob_info.key())


class UploadImageProfileCallback(BaseApiHandler):
    """docstring for UploadImageProfileCallback"""

    def get(self, resource):
        out = dict()
        resource = str(urllib.unquote(resource))
        blob_info = blobstore.BlobInfo.get(resource)
        img_url = get_serving_url(resource, size=100)
        img = "<img src='%s'/>" % img_url
        self.response.headers['Content-Type'] = 'application/json'
        try:
            user_info = self.get_user_info(mem=False)

            try:
                if user_info.img:
                    blob_delete_key = user_info.img
                    delete_serving_url(blob_delete_key)
                    blobstore.delete(blob_delete_key)
                user_info.img = blob_info.key()
                user_info.put()

                mem = dict(
                    id=user_info['id'],
                    display=user_info.display,
                    name=user_info.name,
                    email=user_info.email,
                    country=user_info.country,
                    gender=user_info.gender,
                    bio=user_info.bio,
                    address=user_info.address,
                    phone=user_info.phone,
                    dob_y=user_info.dob.year,
                    dob_m=user_info.dob.month - 1,
                    dob_d=user_info.dob.day,
                    dob=user_info.dob.strftime("%d %B %Y"),
                    img=img
                )
                memcache.replace('app:ajani:ui:%s' % user_info['id'], json.encode(mem))

                out['status'] = "success"
                out['message'] = _('Thanks, your settings have been saved.')
                out['user'] = dict(
                    img=img,
                )
                self.response.out.write(json.encode(out))

            except (AttributeError, KeyError, ValueError), e:
                logging.error('Error updating profile: ' + e)
                out['status'] = "error"
                out['message'] = _('Unable to update profile. Please try again later.')
                delete_serving_url(blob_info.key())
                blobstore.delete(blob_info.key())
                # out['user'] = dict(img=img)
                self.response.out.write(json.encode(out))

        except (AttributeError, TypeError):
            out['status'] = "error"
            out['message'] = _('Sorry you are not logged in.')
            self.response.out.write(json.encode(out))


class UploadImageItemHandler(blobstore_handlers.BlobstoreUploadHandler):
    """docstring for UploadImageItemHandler"""

    def post(self):
        upload_files = self.get_uploads('imagefiles')
        blob_info = upload_files[0]
        self.redirect('/_/upload-iitem-callback/%s' % blob_info.key())


class UploadImageItemCallback(BaseApiHandler):
    """docstring for UploadImageItemCallback"""

    def get(self, resource):
        resource = str(urllib.unquote(resource))
        # blob_info = blobstore.BlobInfo.get(resource)
        img_url = get_serving_url(resource)
        img_th_url = get_serving_url(resource, 100)
        img_th_small_url = get_serving_url(resource, 80)
        img_deldirect_url = '/_/upload-iitem-delete/%s' % resource
        out = dict(
            message="success",
            status="success",
            img=dict(
                key=resource,
                url=img_url,
                th_url=img_th_url,
                th_small_url=img_th_small_url,
                del_url=img_deldirect_url
            )
        )
        self.response.headers['Content-Type'] = 'application/json'
        self.response.out.write(json.encode(out))


class UploadImageItemDeleteHandler(BaseApiHandler):
    """docstring for UploadImageItemCallback"""

    def delete(self, resource):
        out = dict(status="error", message="No Such File")
        resource = str(urllib.unquote(resource))
        blob_info = blobstore.BlobInfo.get(resource)
        if blob_info:
            delete_serving_url(blob_info.key())
            blobstore.delete(blob_info.key())
            out = dict(status="success", message="Deleted")
        self.out(out)


#######################################################
### Messaging Handlers
###
###
#######################################################
class MessageNewHandler(BaseApiHandler):
    """docstring for NewMessageHandler"""

    def post(self):
        form = json.decode(self.request.body)
        out = dict(status='error', message='Login Required')
        user_info = self.get_user_info(mem=True)
        if user_info:
            if self.send_message(
                form['rec']['id'],
                sender=user_info['id'],
                title=form['title'],
                content=form['content'],
                item=form['item']['id']):
                out['status'] = 'success'
                out['message'] = 'success'
            else:
                out['status'] = 'error'
                out['message'] = 'Sending Message Error'
        self.out(out)


class MessageReadHandler(BaseApiHandler):
    """docstring for MessageReadHandler"""

    def put(self):
        out = dict(status='error', message='Unauthorized')
        user_info = self.get_user_info(mem=True)
        if user_info:
            form = json.decode(self.request.body)
            i = self.request.get('i', default_value=None)
            if i:
                msg = models.Message.get_by_id(int(i))
                logging.info(msg)
                if msg:
                    msg_key = msg.key
                    msg.read = True
                    msg.put()

                    ibr = json.decode(memcache.get('app:ajani:ibr%s' % user_info['id']))
                    check = msg_key.urlsafe()
                    if check in ibr:
                        ibr.remove(check)
                        if len(ibr) == 0:
                            form['read'] = True
                        memcache.set('app:ajani:ibr%s' % user_info['id'], json.encode(ibr))
            self.out(form)
        else:
            self.out(out)


class MessageListHandler(BaseApiHandler):
    """docstring for MessageListHandler"""

    def get(self):
        out = dict(status='error', message='Unauthorized')
        user_info = self.get_user_info(mem=True)
        if user_info:
            ct = self.request.get('ct', default_value=None)
            q = self.request.get('q', default_value=None)
            p = self.request.get('p', default_value=None)
            c = self.request.get('c', default_value=None)
            forw = True if p != 'prev' else False
            curs = Cursor(urlsafe=c)
            ibc = None
            ibc_future = None
            obc = None
            obc_future = None
            read_future = None

            user_key = ndb.Key(models.User, user_info['id'])

            if ct:
                ibc = memcache.get('app:ajani:ibc%s' % user_info['id'])
                if not ibc:
                    ibc_future = models.Message.query(models.Message.receiver == user_key).count_async(keys_only=True)
                else:
                    out['ibc'] = ibc
                    out['pibc'] = ibc / 10

                obc = memcache.get('app:ajani:obc%s' % user_info['id'])
                if not obc:
                    obc_future = models.Message.query(models.Message.sender == user_key).count_async(keys_only=True)
                else:
                    out['obc'] = obc
                    out['pobc'] = obc / 10

            read = memcache.get('app:ajani:ibr%s' % user_info['id'])
            if read is None:
                read_future = models.Message.query(ndb.AND(models.Message.receiver == user_key, models.Message.read == False)).fetch_async(keys_only=True)

            # TODO: with memcache
            if q == "inbox":
                query = models.Message.query(models.Message.receiver == ndb.Key(models.User, user_info['id']))
            elif q == "outbox":
                query = models.Message.query(models.Message.sender == ndb.Key(models.User, user_info['id']))

            PAGE_SIZE = 10

            if forw:
                msgs_q, next_cursor, more = query.order(-models.Message.created).fetch_page(PAGE_SIZE, start_cursor=curs)
                if next_cursor and more:
                    out['next_cursor'] = next_cursor.urlsafe()
                if c:
                    out['prev_cursor'] = curs.reversed().urlsafe()
            else:
                msgs_q, next_cursor, more = query.order(models.Message.created).fetch_page(PAGE_SIZE, start_cursor=curs)
                msgs_q = list(reversed(msgs_q))
                if next_cursor and more:
                    out['prev_cursor'] = next_cursor.urlsafe()
                out['next_cursor'] = curs.reversed().urlsafe()

            user_list = []
            item_list = []
            for m in msgs_q:
                if q == "inbox" and m.sender:
                    user = m.sender.get()
                elif q == "outbox":
                    user = m.receiver.get()
                else:
                    user = None

                if q == "inbox" and m.item:
                    item = m.item.get()
                elif q == "outbox":
                    item = m.receiver.get()
                else:
                    item = None

                if user:
                    if user.name:
                        name = user.name
                    elif not user.name and user.display:
                        name = user.display
                else:
                    name = 'Administrator'

                uobj = dict(id=user.key.id() if user else None, name=name)
                iobj = dict(id=item.key.id() if item else None, title=item.title if item else '-')
                user_list.append(uobj)
                item_list.append(iobj)

            if ibc_future:
                ibc = ibc_future.get_result()
                memcache.add('app:ajani:ibc%s' % user_info['id'], ibc)
                out['ibc'] = ibc
                out['pibc'] = ibc / 10

            if obc_future:
                obc = obc_future.get_result()
                memcache.add('app:ajani:obc%s' % user_info['id'], obc)
                out['obc'] = obc
                out['pobc'] = obc / 10

            if read_future:
                ibr_msgs = read_future.get_result()
                if ibr_msgs:
                    ibr_keys = []
                    for ms in ibr_msgs:
                        ibr_keys.append(ms.urlsafe())
                    memcache.add('app:ajani:ibr%s' % user_info['id'], json.encode(ibr_keys))
                    out['read'] = False
                else:
                    memcache.add('app:ajani:ibr%s' % user_info['id'], json.encode([]))
                    out['read'] = True
            else:
                out['read'] = len(json.decode(read)) == 0

            out['status'] = "success"
            out['message'] = "success"
            out['msgs'] = msgs_q
            out['users'] = user_list
            out['items'] = item_list
        self.out(out)


#######################################################
### Admin Handlers
###
###
#######################################################
class UserQueryHandler(BaseApiHandler):
    """docstring for UserQueryHandler"""

    def get(self):
        out = dict(next_cursor=None, prev_cursor=None, users=[])
        ct = self.request.get('ct', default_value=None)
        q = self.request.get('q', default_value=None)
        p = self.request.get('p', default_value=None)
        c = self.request.get('c', default_value=None)
        count = None
        count_future = None
        try:
            if ct:
                count = memcache.get('app:ajani:ucount')
                if not count:
                    count_future = models.User.query().count_async(keys_only=True)
                else:
                    out['count'] = count
                    out['pcount'] = count / 10

            forw = True if p != 'prev' else False
            curs = Cursor(urlsafe=c)

            if q:
                query = models.User.query(models.User.display == q)
            else:
                query = models.User.query()
            PAGE_SIZE = 10

            if forw:
                users_q, next_cursor, more = query.order(-models.User.created).fetch_page(PAGE_SIZE, start_cursor=curs)
                if next_cursor and more:
                    out['next_cursor'] = next_cursor.urlsafe()
                if c:
                    out['prev_cursor'] = curs.reversed().urlsafe()
            else:
                users_q, next_cursor, more = query.order(models.User.created).fetch_page(PAGE_SIZE, start_cursor=curs)
                users_q = list(reversed(users_q))
                if next_cursor and more:
                    out['prev_cursor'] = next_cursor.urlsafe()
                out['next_cursor'] = curs.reversed().urlsafe()

            if count_future:
                count = count_future.get_result()
                memcache.add('app:ajani:ucount', count)
                out['count'] = count
                out['pcount'] = count / 10

            out['status'] = "success"
            out['message'] = "success"
            out['users'] = users_q
        except Exception, e:
            logging.error(e)
            out['status'] = "error"
            out['message'] = "error on getting users list"
        finally:
            self.out(out)


class ItemQueryHandler(BaseApiHandler):
    """docstring for ItemQueryHandler"""

    def get(self):
        out = dict(next_cursor=None, prev_cursor=None, items=[])
        ct = self.request.get('ct', default_value=None)
        q = self.request.get('q', default_value=None)
        p = self.request.get('p', default_value=None)
        c = self.request.get('c', default_value=None)
        count = None
        count_future = None
        try:
            if ct:
                count = memcache.get('app:ajani:icount')
                if not count:
                    count_future = models.Item.query().count_async(keys_only=True)
                else:
                    out['count'] = count
                    out['pcount'] = count / 10

            forw = True if p != 'prev' else False
            curs = Cursor(urlsafe=c)

            if q:
                query = models.Item.query(models.Item.display == q)
            else:
                query = models.Item.query()
            PAGE_SIZE = 10

            if forw:
                items_q, next_cursor, more = query.order(-models.Item.created).fetch_page(PAGE_SIZE, start_cursor=curs)
                if next_cursor and more:
                    out['next_cursor'] = next_cursor.urlsafe()
                if c:
                    out['prev_cursor'] = curs.reversed().urlsafe()
            else:
                items_q, next_cursor, more = query.order(models.Item.created).fetch_page(PAGE_SIZE, start_cursor=curs)
                items_q = list(reversed(items_q))
                if next_cursor and more:
                    out['prev_cursor'] = next_cursor.urlsafe()
                out['next_cursor'] = curs.reversed().urlsafe()

            if count_future:
                count = count_future.get_result()
                memcache.add('app:ajani:icount', count)
                out['count'] = count
                out['pcount'] = count / 10

            out['status'] = "success"
            out['message'] = "success"
            out['items'] = items_q
        except Exception, e:
            logging.error(e)
            out['status'] = "error"
            out['message'] = "error on getting items list"
        finally:
            self.out(out)
